/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.com.seguradora.model.repository.impl;

import br.com.seguradora.exception.PersistenciaException;
import br.com.seguradora.model.Associado;
import br.com.seguradora.model.Foto;
import br.com.seguradora.model.Modelo;
import br.com.seguradora.model.Veiculo;
import br.com.seguradora.model.Vistoria;
import br.com.seguradora.model.constant.TipoVeiculo;
import br.com.seguradora.model.repository.TodasVistorias;
import br.com.seguradora.persistence.GerenciadorDeConexao;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 *
 * @author Diego
 */
public class TodasVistoriasImpl implements TodasVistorias {

    private Connection conn;
    private PreparedStatement pr;
    private ResultSet rs;

    @Override
    public boolean inserir(Vistoria vistoria) throws PersistenciaException {
        if (vistoria == null) {
            throw new PersistenciaException("Não foi informado a vistoria a cadastrar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("INSERT INTO VISTORIA(ID, VALOR, DATA, ID_VEICULO) VALUES(NULL, ?, ?, ?);",
                    Statement.RETURN_GENERATED_KEYS);
            pr.setDouble(1, vistoria.getValor());
            pr.setDate(2, new java.sql.Date(vistoria.getData().getTime()));
            pr.setLong(3, vistoria.getVeiculo().getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
                rs = pr.getGeneratedKeys();
                rs.first();
                long id = rs.getLong(1);
                vistoria.setId(id);

                inserirFotos(vistoria);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível cadastrar a vistoria.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return sucesso;
    }

    @Deprecated
    @Override
    public boolean atualizar(Vistoria vistoria) throws PersistenciaException {
        if (vistoria == null) {
            throw new PersistenciaException("Não foi informado a vistoria a atualizar.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("UPDATE VISTORIA SET VALOR=?, DATA=?, ID_VEICULO=? WHERE ID=?;");
            pr.setDouble(1, vistoria.getValor());
            pr.setDate(2, new java.sql.Date(vistoria.getData().getTime()));
            pr.setLong(3, vistoria.getVeiculo().getId());
            pr.setLong(4, vistoria.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível atualizar a vistoria.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public boolean excluir(Vistoria vistoria) throws PersistenciaException {
        if (vistoria == null) {
            throw new PersistenciaException("Não foi informado a vistoria a excluir.");
        }
        boolean sucesso = false;
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("DELETE FROM VISTORIA WHERE ID=?;");
            pr.setLong(1, vistoria.getId());
            int linhas = pr.executeUpdate();
            if (linhas > 0) {
                pr = conn.prepareStatement("DELETE FROM FOTO_VISTORIA WHERE ID_VISTORIA=?;");
                pr.setLong(1, vistoria.getId());
                sucesso = true;
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível excluir a vistoria.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr);
        }
        return sucesso;
    }

    @Override
    public List<Vistoria> listarTodos(int... limit) throws PersistenciaException {
        List<Vistoria> lista = new ArrayList<Vistoria>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT VIST.ID, VIST.VALOR, VIST.DATA, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM VISTORIA VIST INNER JOIN VEICULO V ON VIST.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID ORDER BY VIST.ID DESC LIMIT ?,?;");
            pr.setInt(1, limit[0]);
            pr.setInt(2, limit[1]);
            rs = pr.executeQuery();
            while (rs.next()) {
                Vistoria vistoria = this.criarVistoria(rs);
                lista.add(vistoria);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as vistorias.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private Vistoria criarVistoria(ResultSet rs) throws PersistenciaException {
        Vistoria vistoria = null;
        try {
            vistoria = new Vistoria(rs.getLong("ID"));
            vistoria.setValor(rs.getDouble("VALOR"));
            vistoria.setData(rs.getDate("DATA") != null ? new Date(rs.getDate("DATA").getTime()) : null);
            Veiculo veiculo = new Veiculo(rs.getLong("ID_VEICULO"));
            veiculo.setCorPredominante(rs.getString("COR_PREDOMINANTE"));
            veiculo.setModelo(new Modelo(rs.getString("MODELO")));
            veiculo.setTipo(TipoVeiculo.valueOf(rs.getString("TIPO")));
            veiculo.setPlaca(rs.getString("PLACA"));
            veiculo.setAssociado(new Associado(rs.getLong("ID_ASSOCIADO"), rs.getString("NOME_ASSOCIADO")));
            vistoria.setVeiculo(veiculo);
        } catch (SQLException sqlex) {
            StringBuilder msg = new StringBuilder("Não foi possível obter os dados da vistoria.");
            msg.append("\nMotivo: ").append(sqlex.getMessage());
            throw new PersistenciaException(msg.toString());
        }
        return vistoria;
    }

    @Override
    public List<Vistoria> listarPeloAssociado(String nome) throws PersistenciaException {
        List<Vistoria> lista = new ArrayList<Vistoria>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT VIST.ID, VIST.VALOR, VIST.DATA, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM VISTORIA VIST INNER JOIN VEICULO V ON VIST.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID WHERE A.NOME LIKE ? ORDER BY A.NOME");
            pr.setString(1, "%" + nome + "%");
            rs = pr.executeQuery();
            while (rs.next()) {
                Vistoria vistoria = this.criarVistoria(rs);
                lista.add(vistoria);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as vistorias pelo associado.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    @Override
    public List<Vistoria> listarPelaPlaca(String placa) throws PersistenciaException {
        List<Vistoria> lista = new ArrayList<Vistoria>();
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT VIST.ID, VIST.VALOR, VIST.DATA, V.ID AS ID_VEICULO, V.COR_PREDOMINANTE, V.TIPO, V.PLACA, M.NOME AS MODELO, A.ID AS ID_ASSOCIADO, A.NOME AS NOME_ASSOCIADO FROM VISTORIA VIST INNER JOIN VEICULO V ON VIST.ID_VEICULO = V.ID INNER JOIN MODELO M ON V.ID_MODELO = M.ID INNER JOIN ASSOCIADO A ON V.ID_ASSOCIADO = A.ID WHERE V.PLACA=? ORDER BY V.PLACA");
            pr.setString(1, placa);
            rs = pr.executeQuery();
            while (rs.next()) {
                Vistoria vistoria = this.criarVistoria(rs);
                lista.add(vistoria);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível listar as vistorias pela placa.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
        return lista;
    }

    private void inserirFotos(Vistoria vistoria) throws PersistenciaException {
        try {
            pr = conn.prepareStatement("DELETE FROM FOTO_VISTORIA WHERE ID_VISTORIA=?;");
            pr.setLong(1, vistoria.getId());
            pr.executeUpdate();
            pr = conn.prepareStatement("INSERT INTO FOTO_VISTORIA (ID, IMAGEM, ID_VISTORIA) VALUES (NULL, ?, ?)");
            for (Foto foto : vistoria.getFotosList()) {
                pr.setBytes(1, foto.toByteArray());
                pr.setLong(2, vistoria.getId());
                pr.executeUpdate();
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível inserir as fotos da vistoria.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        }
    }

    @Override
    public void getFotos(Vistoria vistoria) throws PersistenciaException {
        List<Foto> fotosList = new ArrayList<Foto>();
        vistoria.setFotosList(fotosList);
        try {
            conn = GerenciadorDeConexao.abreConexao();
            pr = conn.prepareStatement("SELECT F.ID, F.IMAGEM FROM FOTO_VISTORIA F INNER JOIN VISTORIA V ON F.ID_VISTORIA = V.ID WHERE F.ID_VISTORIA=?");
            pr.setLong(1, vistoria.getId());
            rs = pr.executeQuery();
            while (rs.next()) {
                Foto foto = Foto.valueOf(rs.getBytes("IMAGEM"));
                foto.setId(rs.getLong("ID"));
                vistoria.getFotosList().add(foto);
            }
        } catch (SQLException exc) {
            StringBuilder msg = new StringBuilder("Não foi possível buscar as fotos da vistoria.");
            msg.append("\nMotivo: ").append(exc.getMessage());
            throw new PersistenciaException(msg.toString());
        } finally {
            GerenciadorDeConexao.fechaConexao(conn, pr, rs);
        }
    }
}
